package com.seari.c3gallery.client;

import com.seari.c3gallery.client.handler.ResCmdHandler;
import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.Unpooled;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.DatagramPacket;
import io.netty.channel.socket.nio.NioDatagramChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.util.CharsetUtil;
import io.netty.util.concurrent.GenericFutureListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.net.InetSocketAddress;
import java.nio.charset.Charset;
import java.util.concurrent.TimeUnit;

public class UDPClient {

    protected static Logger logger = LoggerFactory.getLogger(UDPClient.class);
    private static UDPClient instance;

    private String remoteHost;
    private int remoteport;
    private int localPort;

    private UDPClient(){}

    private UDPClient(String remoteHost,int remoteport,int localPort){
        this.remoteHost = remoteHost;
        this.remoteport = remoteport;
        this.localPort = localPort;
    }

    public static synchronized UDPClient getInstance(String remoteHost,int remoteport,int localPort){
        if (instance == null) {
            instance = new UDPClient(remoteHost,remoteport,localPort);
        }
        return instance;
    }

    public Channel channel;

    public void setUp() throws Exception {
        NioEventLoopGroup nioEventLoopGroup = new NioEventLoopGroup();

        try {
            Bootstrap bootstrap = new Bootstrap();
            bootstrap.group(nioEventLoopGroup)
                    .channel(NioDatagramChannel.class)
                    .option(ChannelOption.SO_BROADCAST, true)
                    .handler(new ChannelInitializer<Channel>() {

                        @Override
                        protected void initChannel(Channel ch) throws Exception {
                            ch.pipeline().addLast(new StringDecoder(Charset.forName("ASCII")));
                            ch.pipeline().addLast(new ResCmdHandler());
                        }
                    });
            ChannelFuture future = bootstrap.bind(localPort).sync();
            channel = future.channel();
            channel.closeFuture().addListener(new GenericFutureListener<ChannelFuture>() {
                @Override
                public void operationComplete(ChannelFuture f) throws Exception {
                    nioEventLoopGroup.shutdownGracefully();
                }});

            if (future.isSuccess()) {
                logger.info("连接成功");
            }

            //future.channel().closeFuture();

//            channel.writeAndFlush(new DatagramPacket(Unpooled.copiedBuffer("ssss", CharsetUtil.US_ASCII), new InetSocketAddress("127.0.0.1", 10088)));


        } catch (Exception e) {
            logger.warn(e.getMessage());
            nioEventLoopGroup.shutdownGracefully();
        } finally {
            //nioEventLoopGroup.shutdownGracefully();
        }
    }


    //新开窗口
    public void openNewWindow(String param) {
        String cmd = "<OPEN,W_ID,Channel,SubChannel,x0,y0,x1,y1>";
        try {
            sendData(cmd);
            TimeUnit.MILLISECONDS.sleep(10);
        } catch (Exception e) {
            logger.warn(e.getMessage());
        }
    }

    //关闭窗口
    public void shutWindow(int wid) {
        String cmd = "<SHUT,"+ wid +">";
        try {
            sendData(cmd);
            TimeUnit.MILLISECONDS.sleep(10);
        } catch (Exception e) {
            logger.warn(e.getMessage());
        }
    }

    //切换信号源
    public void switchSignalSource(int SourceChl){
        String cmd = "<SWCH,"+ SourceChl +">";
        try {
            sendData(cmd);
            TimeUnit.MILLISECONDS.sleep(10);
        } catch (Exception e) {
            logger.warn(e.getMessage());
        }
    }

    //保存场景
    public void saveScene(int sceneId){
        String cmd = "<SAVE,"+ sceneId +">";
        try {
            sendData(cmd);
            TimeUnit.MILLISECONDS.sleep(10);
        } catch (Exception e) {
            logger.warn(e.getMessage());
        }
    }

    //调出场景
    public void callScene(String sceneId){
        String cmd = "<CALL,"+ sceneId +">";
        try {
            sendData(cmd);
            TimeUnit.MILLISECONDS.sleep(10);
        } catch (Exception e) {
            logger.warn(e.getMessage());
        }
    }


    public void sendData(String obj) {
        channel.writeAndFlush(new DatagramPacket(Unpooled.copiedBuffer(obj, CharsetUtil.US_ASCII), new InetSocketAddress(remoteHost, remoteport)));
    }

    public void reset() throws Exception
    {
        if(null != channel)
        {
            channel.close();
        }
        this.setUp();
    }

    public Channel getChannel() {
        return channel;
    }

    public static void main(String[] args) throws Exception {
        UDPClient client =  UDPClient.getInstance("127.0.0.1",10088,10089);
        client.setUp();
        Thread.sleep(3000);
        client.sendData("<OPEN,1,1,0,0,0,100,100>");
    }


}
